home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / vbcc / pasm / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-24  |  20.0 KB  |  790 lines

  1. /* $VER: pasm eval.c V0.7 (14.12.97)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-97 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.7 (14.12.97) phx
  16.  *      @ha, @h, @l are only allowed at the end of an operand, according
  17.  *      to GNU-as notation. '@' is only allowed as the first character in
  18.  *      a symbol (for @function and @object, for example).
  19.  * v0.5 (11.10.97) phx
  20.  *      getarg() works with \' and \" now.
  21.  * v0.4 (05.07.97) phx
  22.  *      R_PPC_TOC16 and R_PPC_REL14 support in makereloc() and makexref().
  23.  *      "(<term>)@l/h/ha" was not recognized.
  24.  *      A comment introducer '#' was erroneously treated as a macro
  25.  *      parameter in read_macro_params().
  26.  *      Undefined symbols are only automatically declared as externally
  27.  *      defined, if the -x option was given. Otherwise display an
  28.  *      error message.
  29.  *      Implementing backwards-evaluation of an expression in v0.3 was not
  30.  *      very smart (e.g. 4-1+2 => 1(!)) - changed to forward again... ;)
  31.  * v0.3 (20.04.97) phx
  32.  *      Bug in eval_expression() fixed, which sometimes caused the loss
  33.  *      of the last argument of an expression.
  34.  * v0.2 (25.03.97) phx
  35.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  36.  *      or ELF output format may be selected. ELF is default for all
  37.  *      currently supported platforms. PPCasm supports nine different
  38.  *      relocation types (there are much more...).
  39.  *      Compiles and works also under NetBSD/amiga (68k).
  40.  *      Changed function declaration to 'new style' in all sources
  41.  *      (to avoid problems with '...' for example).
  42.  *      makexref() and makereloc() used wrong offset.
  43.  * v0.1 (11.03.97) phx
  44.  *      First test version with all PowerPC instructions and most
  45.  *      important directives. Only raw, absolute output.
  46.  * v0.0 (21.02.97) phx
  47.  *      File created.
  48.  */
  49.  
  50.  
  51. #define EVAL_C
  52. #include "ppcasm.h"
  53.  
  54.  
  55. char *getsymbol(struct GlobalVars *,char *);
  56. char *getarg(struct GlobalVars *,char *);
  57. char *skipspaces(char *);
  58. char *remquotes(char *);
  59. void checkEOL(char *);
  60. char *skipexpression(struct GlobalVars *,char *);
  61. void read_macro_params(struct GlobalVars *,struct ParsedLine *,
  62.                        struct MacroParams *,char *);
  63. char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
  64. uint32 makereloc(struct GlobalVars *,struct Expression *);
  65. uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
  66. char *getintexp(struct GlobalVars *,char *,uint32 *);
  67. char *eval_expression(struct GlobalVars *,struct Expression *,char *);
  68.  
  69. static uint32 hihalf(struct GlobalVars *,uint32);
  70. static uint32 lohalf(struct GlobalVars *,uint32);
  71. static uint32 read_hex(char *);
  72. static uint32 read_dec(char *);
  73. static uint32 read_oct(char *);
  74. static uint32 read_bin(char *);
  75. static uint32 read_str(char *);
  76.  
  77.  
  78.  
  79. /* table of valid symbol characters, 
  80.    0=invalid, 1=valid in whole symbol, 2=valid, but not as first char */
  81. static uint8 valid_symchars[256] = {
  82.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  83.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  84.   0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,  /* $ . */
  85.   2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,1,  /* 0-9 ? */
  86.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  87.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  88.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  89.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  90.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  91.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  92.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  93.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  94.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  95.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  96.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  98. };
  99.  
  100. /* table of valid argument characters, 
  101.    0=invalid, 1=valid, 2=valid, but indicates string */
  102. static uint8 valid_argchars[256] = {
  103.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  104.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  105.   0,0,2,0,1,0,0,2,0,0,0,0,0,0,1,0,  /* " $ ' . */
  106.   1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,  /* 0-9 ? */
  107.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  108.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  109.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  110.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  111.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  112.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  113.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  114.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  115.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  116.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  117.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  119. };
  120.  
  121. /* valid operators */
  122. #define NUMOPS 10
  123. static char valid_operators[NUMOPS] = {
  124.   '+','-','*','/','%','<','>','&','|','^'
  125. };
  126. #define MAXOPPRI 5
  127. static uint8 op_priority[NUMOPS] = {
  128.   4,4,5,5,5,3,3,2,0,1
  129. };
  130.  
  131.  
  132. char *getsymbol(struct GlobalVars *gv,char *s)
  133. /* read a symbol string into gv->strbuf */
  134. {
  135.   uint8 *vsc = valid_symchars;
  136.   char *b = gv->strbuf;
  137.   int bsize = STRBUFSIZE-2;
  138.  
  139.   if (*s == '@') {  /* '@' is allowed as first character */
  140.     *b++ = *s++;
  141.     bsize--;
  142.   }
  143.   if (vsc[(unsigned char)*s] == 1) {  /* first character valid? */
  144.     *b++ = *s++;
  145.     while (vsc[(unsigned char)*s] && bsize--)
  146.       *b++ = *s++;
  147.   }
  148.   *b = 0;
  149.   return (s);
  150. }
  151.  
  152.  
  153. char *getarg(struct GlobalVars *gv,char *s)
  154. /* read next argument into gv->strbuf */
  155. {
  156.   uint8 v,*vac = valid_argchars;
  157.   char c,*b = gv->strbuf;
  158.   int bsize = STRBUFSIZE-1;
  159.  
  160.   if (*s == '@') {  /* '@' is allowed as first character */
  161.     *b++ = *s++;
  162.     bsize--;
  163.   }
  164.   while ((v = vac[(unsigned char)*s]) && bsize--) {
  165.     *b++ = *s++;
  166.     if (v==2) {  /* string? */
  167.       c = *(s-1);
  168.       for (;;) {
  169.         if (bsize--) {
  170.           if (!(*b++ = *s))  /* string can only be terminated by EOL */
  171.             return (s);
  172.         }
  173.         else
  174.           return (s);
  175.         if (*s++ == c) {
  176.           if (*s==c || *(s-2)=='\\') {
  177.             if (bsize--)  /* "", '' \" or \' don't terminate the string */
  178.               *b++ = *s++;
  179.              else
  180.               return (s);
  181.           }
  182.           else
  183.             break;
  184.         }
  185.       }
  186.     }
  187.   }
  188.   *b = 0;
  189.   return (s);
  190. }
  191.  
  192.  
  193. char *skipspaces(char *s)
  194. /* advance string pointer to the first character, which is no white space */
  195. {
  196.   while (*s==' ' || *s=='\t')
  197.     ++s;
  198.   return (s);
  199. }
  200.  
  201.  
  202. char *remquotes(char *s)
  203. /* remove " or ', if present and return new strbuf-pointer */
  204. {
  205.   int len;
  206.   char c = *s;
  207.  
  208.   if (c=='\"' || c=='\'')  /* string is in quotes */
  209.     if (len = strlen(++s) - 1)
  210.       if (s[len] == c)
  211.         s[len] = 0;
  212.   return (s);
  213. }
  214.  
  215.  
  216. void checkEOL(char *s)
  217. /* check for illegal extra characters on line */
  218. {
  219.   s = skipspaces(s);
  220.   if (*s && *s!='#')  /* only comment is allowed as an extra character */
  221.     error(18);  /* extra characters on line */
  222. }
  223.  
  224.  
  225. char *skipexpression(struct GlobalVars *gv,char *s)
  226. {
  227.   char c;
  228.  
  229.   do {
  230.     s = getarg(gv,s);
  231.     s = skipspaces(s);
  232.     c = *s++;
  233.   }
  234.   while (c!=0 && c!='#' && c!=',');
  235.   return (--s);
  236. }
  237.  
  238.  
  239. void read_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  240.                        struct MacroParams *mp,char *op)
  241. /* read parameters and store pointers to their first character */
  242. {
  243.   char c;
  244.  
  245.   mp->param[0] = mp->param0;
  246.   if (pl->branch_hint)
  247.     mp->param0[0] = pl->branch_hint>0 ? '+' : '-';
  248.   for (;;) {
  249.     op = skipspaces(op);
  250.     c = *op;
  251.     if (c!=0 && c!='#') {  /* another parameter? */
  252.       if (mp->narg < (MAX_MACPARAMS-1)) {
  253.         mp->param[++mp->narg] = op;
  254.         op = skipexpression(gv,op);
  255.         c = *op;
  256.         if (c==0 || c=='#') {
  257.           *op = 0;  /* end of line / start of comment */
  258.           return;
  259.         }
  260.         *op++ = 0;  /* next parameter */
  261.       }
  262.       else {
  263.         error(11);  /* too many macro parameters */
  264.         return;
  265.       } 
  266.     }
  267.     else
  268.       return;
  269.   }
  270. }
  271.  
  272.  
  273. char *getexp(struct GlobalVars *gv,char *s,uint32 *val,uint8 size)
  274. /* evaluate expression, create relocations or x-references, if required */
  275. {
  276.   struct Expression exp;
  277.  
  278.   s = eval_expression(gv,&exp,s);
  279.   if (exp.type != SYM_UNDEF) {
  280.     if (exp.reloctype==R_PPC_ADDR32 && size==2)
  281.       exp.reloctype = R_PPC_ADDR16;
  282.     switch (exp.type) {
  283.       case SYM_RELOC:
  284.         *val = makereloc(gv,&exp);  /* make relocation entry */
  285.         break;
  286.       case SYM_EXTERN:  /* reference to external symbol */
  287.         *val = makexref(gv,&exp,size);
  288.         break;
  289.       default:  /* SYM_ABS */
  290.         *val = exp.value;
  291.         break;
  292.     }
  293.   }
  294.   else
  295.     error(19);  /* undefined symbol */
  296.   return (s);
  297. }
  298.  
  299.  
  300. static uint32 hihalf(struct GlobalVars *gv,uint32 x)
  301. {
  302.   if (gv->signedexp)
  303.     return ((int32)x/0x10000);
  304.   else
  305.     return (x>>16);
  306. }
  307.  
  308.  
  309. static uint32 lohalf(struct GlobalVars *gv,uint32 x)
  310. {
  311.   if (gv->signedexp)
  312.     return ((int16)x);
  313.   else
  314.     return (x&0xffff);
  315. }
  316.  
  317.  
  318. uint32 makereloc(struct GlobalVars *gv,struct Expression *exp)
  319. /* make new relocation entry for current section */
  320. {
  321.   struct Reloc *reloc = alloc(sizeof(struct Reloc));
  322.  
  323.   reloc->relocsect = exp->symbol->relsect;
  324.   reloc->offset = gv->csect->pc;
  325.   reloc->type = exp->reloctype;
  326.   reloc->addend = exp->value;
  327.   addtail(&gv->csect->reloclist,&reloc->n);
  328.   switch (exp->reloctype) {
  329.     case R_PPC_ADDR16_HA:
  330.     case R_PPC_ADDR16_HI:
  331.       reloc->offset += 2;
  332.       return (hihalf(gv,exp->value));
  333.     case R_PPC_ADDR16_LO:
  334.       reloc->offset += 2;
  335.       return (lohalf(gv,exp->value));
  336.     case R_PPC_TOC16:
  337.       reloc->offset += 2;
  338.       return (exp->value);
  339.     case R_PPC_REL14:
  340.     case R_PPC_REL14_BRTAKEN:
  341.     case R_PPC_REL14_BRNTAKEN:
  342.       if (gv->output == OFMT_EHF) {
  343.         reloc->offset += 2;
  344.         return (exp->value + 2);
  345.       }
  346.     default:
  347.       return (exp->value);
  348.   }
  349. }
  350.  
  351.  
  352. uint32 makexref(struct GlobalVars *gv,struct Expression *exp,uint8 size)
  353. {
  354.   struct XReference *xref = alloc(sizeof(struct XReference));
  355.  
  356.   xref->xsymbol = exp->symbol;
  357.   xref->offset = gv->csect->pc;
  358.   xref->addend = exp->value;
  359.   xref->type = exp->reloctype;
  360.   xref->size = size;
  361.   addtail(&gv->csect->xreflist,&xref->n);
  362.   switch (exp->reloctype) {
  363.     case R_PPC_ADDR16_HA:
  364.     case R_PPC_ADDR16_HI:
  365.       xref->offset += 2;
  366.       return (hihalf(gv,exp->value));
  367.     case R_PPC_ADDR16_LO:
  368.       xref->offset += 2;
  369.       return (lohalf(gv,exp->value));
  370.     case R_PPC_TOC16:
  371.       xref->offset += 2;
  372.       return (exp->value);
  373.     case R_PPC_REL14:
  374.     case R_PPC_REL14_BRTAKEN:
  375.     case R_PPC_REL14_BRNTAKEN:
  376.       if (gv->output == OFMT_EHF) {
  377.         xref->offset += 2;
  378.         return (exp->value + 2);
  379.       }
  380.     default:
  381.       return (exp->value);
  382.   }
  383. }
  384.  
  385.  
  386. char *getintexp(struct GlobalVars *gv,char *s,uint32 *val)
  387. /* evaluate expression and check if absolute integer */
  388. {
  389.   struct Expression exp;
  390.  
  391.   s = eval_expression(gv,&exp,s);
  392.   if (exp.type != SYM_UNDEF) {
  393.     if (exp.type == SYM_ABS)
  394.       *val = exp.value;
  395.     else
  396.       error(24);  /* constant integer expression required */
  397.   }
  398.   else
  399.     error(19);  /* undefined symbol */
  400.   return (s);
  401. }
  402.  
  403.  
  404. char *eval_expression(struct GlobalVars *gv,struct Expression *exp_result,
  405.                       char *s)
  406. /* evaluate an integer expression and determine its type */
  407. {
  408.   struct Expression exp[EXPSTACKSIZE];
  409.   uint8 ops[EXPSTACKSIZE-1],op,ta,tb;
  410.   int i,j,k,exp_args=0;
  411.   uint8 unary;  /* unary operator, 0=none, 1=plus, 2=minus, 3=not */
  412.   char c;
  413.   char *arg=gv->strbuf;
  414.   struct Symbol *sym;
  415.  
  416.   exp_result->value = 0;
  417.   exp_result->type = SYM_UNDEF;
  418.  
  419.   /* build expression stack */
  420.   for (;;) {
  421.     unary = 0;
  422.     exp[exp_args].reloctype = R_PPC_ADDR32;
  423.  
  424.     for (;;) {
  425.       s = skipspaces(s);
  426.       s = getarg(gv,s);  /* try to get next argument */
  427.       if (c = *arg)
  428.         break;  /* got it */
  429.  
  430.       if ((c=*s++) == '(') {  /* beginning of a term? */
  431.         s = eval_expression(gv,&exp[exp_args],s);
  432.         if (*s++ != ')') {
  433.           error(21);  /* missing closing parenthesis */
  434.           s--;
  435.         }
  436.         *arg = 0;  /* expression in term is already evaluated */
  437.         break;
  438.       }
  439.  
  440.       if (c==0 || c=='#' || c==')') {
  441.         error(17);  /* missing argument */
  442.         s--;
  443.         c = 0;
  444.         break;
  445.       }
  446.  
  447.       if (unary)
  448.         error(20);  /* double unary operator */
  449.       else
  450.         switch (c) {
  451.           case '+':
  452.             unary = 1;
  453.             break;
  454.           case '-':
  455.             unary = 2;
  456.             break;
  457.           case '~':
  458.             unary = 3;
  459.             break;
  460.           default:
  461.             error(13);  /* syntax error */
  462.             break;
  463.         }
  464.     }
  465.  
  466.     if (!c)
  467.       break;  /* evaluate */
  468.  
  469.     if (c = *arg) {
  470.  
  471.       if (c>='0' && c<='9') {  /* numeric constant */
  472.         if (c=='0')
  473.           switch (arg[1]) {
  474.             case 'x':
  475.               exp[exp_args].value = read_hex(&arg[2]);
  476.               break;
  477.             case 'b':
  478.               exp[exp_args].value = read_bin(&arg[2]);
  479.               break;
  480.             case 0:
  481.               exp[exp_args].value = 0;
  482.               break;
  483.             default:
  484.               exp[exp_args].value = read_oct(&arg[1]);
  485.               break;
  486.           }
  487.         else
  488.           exp[exp_args].value = read_dec(arg);
  489.         exp[exp_args].type = SYM_ABS;
  490.       }
  491.  
  492.       else if (c=='\"' || c=='\'') {  /* string constant */
  493.         exp[exp_args].value = read_str(arg);
  494.         exp[exp_args].type = SYM_ABS;
  495.       }
  496.  
  497.       else {  /* get symbol value */
  498.         if (sym = search_symbol(gv,arg)) {
  499.           exp[exp_args].value = sym->value;
  500.           exp[exp_args].type = sym->type;
  501.           exp[exp_args].symbol = sym;
  502.         }
  503.         else {
  504.           if (gv->pass && gv->autoextern) {  /* pass 2? auto. decl. extern */
  505.             sym = add_symbol(gv,arg,SYM_EXTERN,0);
  506.             exp[exp_args].value = sym->value;
  507.             exp[exp_args].type = sym->type;
  508.             exp[exp_args].symbol = sym;
  509.           }
  510.           else {
  511.             exp[exp_args].value = 0;
  512.             exp[exp_args].type = SYM_UNDEF;
  513.           }
  514.         }
  515.       }
  516.     }
  517.  
  518.     if (unary) {
  519.       if (exp[exp_args].type >= SYM_RELOC)
  520.         error(22);  /* illegal operation for a relocatable expression */
  521.       else
  522.         switch (unary) {
  523.           case 2:  /* negate */
  524.             exp[exp_args].value = -exp[exp_args].value;
  525.             break;
  526.           case 3:  /* not */
  527.             exp[exp_args].value = ~exp[exp_args].value;
  528.             break;
  529.         }
  530.     }
  531.     if (exp[exp_args].type == SYM_ABS)
  532.       exp[exp_args].reloctype = R_NONE;
  533.  
  534.     /* check for operator */
  535.     s = skipspaces(s);
  536.     c = *s;
  537.     i = 0;
  538.     while (i<NUMOPS) {
  539.       if (c == valid_operators[i])
  540.         break;
  541.       i++;
  542.     }
  543.     if (i==NUMOPS)
  544.       break;  /* end of expression - evaluate */
  545.  
  546.     ops[exp_args++] = i;
  547.     if (*(++s) == c)
  548.       if (i==5 || i==6)  /* <<, >> */
  549.         ++s;
  550.   }
  551.  
  552.   /* evaluate expression stack */
  553.   for (i=MAXOPPRI; i>=0; i--) {
  554.     for (j=0; j<exp_args; ) {
  555.       op = ops[j];
  556.       if (op_priority[op] == i) {
  557.         if (!(ta = exp[j].type) || !(tb = exp[j+1].type)) {
  558.           exp[j].value = 0;
  559.           exp[j].type = SYM_UNDEF;
  560.           exp[j].reloctype = R_PPC_ADDR32;
  561.         }
  562.         else switch(op) {
  563.  
  564.           case 0:  /* + */
  565.             if (ta != tb) {
  566.               if (ta == SYM_ABS) {
  567.                 exp[j].type = tb;  /* reloc + abs = reloc */
  568.                 exp[j].reloctype = exp[j+1].reloctype;
  569.                 exp[j].symbol = exp[j+1].symbol;
  570.               }
  571.               else if (tb != SYM_ABS) {
  572.                 error(22);  /* illegal reloc operation */
  573.                 break;
  574.               }          
  575.             }
  576.             else if (ta >= SYM_RELOC) {
  577.               error(22);
  578.               break;
  579.             }
  580.             exp[j].value += exp[j+1].value;
  581.             break;
  582.  
  583.           case 1:  /* - */
  584.             if (ta != tb) {  /* reloc - abs = reloc */
  585.               if (tb != SYM_ABS) {
  586.                 error(22);
  587.                 break;
  588.               }
  589.             }
  590.             else {  /* reloc - reloc = abs  |  abs - abs = abs */
  591.               if (ta != SYM_EXTERN) {  /* extern - extern  not supported */
  592.                 exp[j].type = SYM_ABS;
  593.                 if (ta == SYM_RELOC)
  594.                   if (exp[j].symbol->relsect != exp[j+1].symbol->relsect)
  595.                     error(23);  /* symbols reside in different sections */
  596.               }
  597.               else {
  598.                 error(22);
  599.                 break;
  600.               }
  601.             }
  602.             exp[j].value -= exp[j+1].value;
  603.             break;
  604.  
  605.           case 2:  /* * */
  606.             if (ta == tb == SYM_ABS)
  607.               exp[j].value *= exp[j+1].value;
  608.             else
  609.               error(22);
  610.             break;
  611.  
  612.           case 3:  /* / */
  613.             if (ta == tb == SYM_ABS)
  614.               exp[j].value /= exp[j+1].value;
  615.             else
  616.               error(22);
  617.             break;
  618.  
  619.           case 4:  /* % */
  620.             if (ta == tb == SYM_ABS)
  621.               exp[j].value %= exp[j+1].value;
  622.             else
  623.               error(22);
  624.             break;
  625.  
  626.           case 5:  /* << */
  627.             if (ta == tb == SYM_ABS)
  628.               exp[j].value <<= exp[j+1].value;
  629.             else
  630.               error(22);
  631.             break;
  632.  
  633.           case 6:  /* << */
  634.             if (ta == tb == SYM_ABS)
  635.               exp[j].value >>= exp[j+1].value;
  636.             else
  637.               error(22);
  638.             break;
  639.  
  640.           case 7:  /* & */
  641.             if (ta == tb == SYM_ABS)
  642.               exp[j].value &= exp[j+1].value;
  643.             else
  644.               error(22);
  645.             break;
  646.  
  647.           case 8:  /* | */
  648.             if (ta == tb == SYM_ABS)
  649.               exp[j].value |= exp[j+1].value;
  650.             else
  651.               error(22);
  652.             break;
  653.  
  654.           case 9:  /* ^ */
  655.             if (ta == tb == SYM_ABS)
  656.               exp[j].value ^= exp[j+1].value;
  657.             else
  658.               error(22);
  659.             break;
  660.         }
  661.  
  662.         exp_args--;
  663.         for (k=j; k<exp_args; k++) {
  664.           memcpy(&exp[k+1],&exp[k+2],sizeof(struct Expression));
  665.           ops[k] = ops[k+1];
  666.         }
  667.       }
  668.       else
  669.         j++;
  670.     }
  671.     if (exp_args==0)
  672.       break;
  673.   }
  674.  
  675.   memcpy(exp_result,&exp[0],sizeof(struct Expression));
  676.   if (*s == '@') {  /* check for @ha, @h or @l */
  677.     s++;
  678.     switch (tolower((unsigned char)*s++)) {
  679.       case 'l':  /* symbol@l : lower half-word */
  680.         if (exp_result->type == SYM_ABS) {
  681.           exp_result->reloctype = R_NONE;
  682.           exp_result->value = lohalf(gv,exp_result->value);
  683.         }
  684.         else
  685.           exp_result->reloctype = R_PPC_ADDR16_LO;
  686.         break;
  687.       case 'h':
  688.         if (tolower((unsigned char)*s) == 'a') {
  689.           s++;  /* symbol@ha : higher (addi) */
  690.           if (exp_result->type == SYM_ABS) {
  691.             exp_result->reloctype = R_NONE;
  692.             if (exp_result->value & 0x8000)
  693.               exp_result->value = hihalf(gv,exp_result->value + 0x10000);
  694.             else
  695.               exp_result->value = hihalf(gv,exp_result->value);
  696.           }
  697.           else
  698.             exp_result->reloctype = R_PPC_ADDR16_HA;
  699.         }
  700.         else {  /* symbol@h : higher half-word */
  701.           if (exp_result->type == SYM_ABS) {
  702.             exp_result->reloctype = R_NONE;
  703.             exp_result->value = hihalf(gv,exp_result->value);
  704.           }
  705.           else
  706.             exp_result->reloctype = R_PPC_ADDR16_HI;
  707.         }
  708.         break;
  709.       default:
  710.         s -= 2;
  711.         break;
  712.     }
  713.   }
  714.  
  715.   return (s);
  716. }
  717.  
  718.  
  719. static uint32 read_hex(char *s)
  720. {
  721.   uint32 x=0,y;
  722.  
  723.   while (y = (unsigned char)*s++) {
  724.     if (y > '9')
  725.       y = (y & 0x5f) - 7;
  726.     x <<= 4;
  727.     x += y - '0';
  728.   }
  729.   return (x);
  730. }
  731.  
  732.  
  733. static uint32 read_dec(char *s)
  734. {
  735.   uint32 x=0,y;
  736.  
  737.   while (y = (unsigned char)*s++) {
  738.     x *= 10;
  739.     x += y - '0';
  740.   }
  741.   return (x);
  742. }
  743.  
  744.  
  745. static uint32 read_oct(char *s)
  746. {
  747.   uint32 x=0,y;
  748.  
  749.   while (y = (unsigned char)*s++) {
  750.     x <<= 3;
  751.     x += y - '0';
  752.   }
  753.   return (x);
  754. }
  755.  
  756.  
  757. static uint32 read_bin(char *s)
  758. {
  759.   uint32 x=0,y;
  760.  
  761.   while (y = (unsigned char)*s++) {
  762.     x <<= 1;
  763.     x += y & 1;
  764.   }
  765.   return (x);
  766. }
  767.  
  768.  
  769. static uint32 read_str(char *s)
  770. {
  771.   uint32 x=0;
  772.   char c,sc=*s++;
  773.  
  774.   while (c = *s++) {
  775.     if (c==sc) {
  776.       if (*s==sc)   /* "" is converted into " */
  777.         s++;
  778.       else
  779.         break;
  780.     }
  781.     else if (c=='\\') {
  782.       if (!(c = escchar(*s++)))
  783.         break;
  784.     }
  785.     x <<= 8;
  786.     x += (unsigned char)c;
  787.   }
  788.   return (x);
  789. }
  790.